package org.mspring.mlog.api.regioncache;

import net.sf.ehcache.Ehcache;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.mspring.mlog.api.regioncache.key.Generator;
import org.mspring.mlog.api.regioncache.task.AddRegionCacheTask;
import org.mspring.mlog.api.regioncache.task.RemoveRegionCacheTask;
import org.mspring.platform.cache.service.CacheService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author Gao Youbo
 * @since 2013年12月29日
 */
@Aspect
@Component
public class RegionCacheAspect {
    private static final Logger log = LoggerFactory.getLogger(RegionCacheAspect.class);

    @Autowired
    private RemoveRegionCacheTask removeRegionCacheTask;
    @Autowired
    private AddRegionCacheTask addRegionCacheTask;
    @Autowired
    private CacheService cacheService;

    /**
     * 删除或者更新缓存
     * 
     * @param point
     * @param regionCache
     */
    @AfterReturning("within(org.mspring.mlog..*) && @annotation(regionCache)")
    public void afterReturning(JoinPoint point, RegionCache regionCache) {
        if (regionCache.action() == RegionCacheAction.ADD) {
            return;
        }
        String cacheName = regionCache.cacheName();
        cacheService.clearCache(cacheName);
    }

    /**
     * 访问方法前如果存在缓存直接从缓存中获取数据
     * 
     * @param point
     * @param regionCache
     * @throws Throwable
     */
    @Before("within(org.mspring.mlog..*) && @annotation(regionCache)")
    public Object before(JoinPoint point, RegionCache regionCache) throws Throwable {
        if (regionCache.action() == RegionCacheAction.REMOVE) {
            return null;
        }
        String cacheName = regionCache.cacheName();
        String cacheKey = Generator.generate(point, regionCache);
        Object value = cacheService.getCacheValue(cacheName, cacheKey);
        if (value != null) {
            return value;
        }
        if (point.getClass().equals(MethodInvocationProceedingJoinPoint.class)) {
            value = ((MethodInvocationProceedingJoinPoint) point).proceed();
            Ehcache cache = cacheService.addCache(cacheName, 1000, 3600, 3600);
            cacheService.updateCacheValue(cache, cacheKey, value);
            return value;
        }
        return null;
    }
}
